package com.genghis.rapidcrm.web.view;

import com.genghis.rapidcrm.kernel.UsersRecordModel;
import com.genghis.rapidcrm.util.RapidResourceUtil;
import com.genghis.rapidcrm.util.RapidStrUtil;
import com.genghis.rapidcrm.web.view.model.RapidCssScriptModel;
import com.genghis.rapidcrm.web.view.model.RapidJsScriptModel;
import com.genghis.rapidcrm.web.view.support.RapidJavaScript;
import com.genghis.rapidcrm.web.view.support.RapidLoader;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

public abstract class RapidControllerView extends RapidActionView {

    RapidViewer viewer;

    protected RapidViewer getViewer(HttpServletRequest request) {
        if (viewer == null) {
            viewer = new RapidViewer(this);
            viewer.assign("APPTITLE", getTranslatedString("APPTITLE", request));
            viewer.assign("RAPIDCRM_VERSION", getAppConfig().getProperty("rapidcrm.current_version"));
            viewer.assign("MODULE_NAME", getModule(request));
        }
        return viewer;
    }

    private String getTranslatedString(String code, HttpServletRequest request) {
        return getLanguageHandler(request).vtranslate(code, "");
    }

    String getPageTitle(HttpServletRequest request) {
        return getLanguageHandler(request).vtranslate(getModule(request), request.getParameter("module"));
    }

    @Override
    protected void preProcess(HttpServletRequest request, HttpServletResponse response, boolean display)
            throws Exception {

        UsersRecordModel currentUser = UsersRecordModel.getCurrentUserModel(request);
        RapidViewer viewer = this.getViewer(request);
        viewer.assign("PAGETITLE", this.getPageTitle(request));
        viewer.assign("SCRIPTS", this.getHeaderScripts(request));
        viewer.assign("STYLES", this.getHeaderCss(request));
        viewer.assign("SKIN_PATH", getThemeHandler(request).getCurrentUserThemePath(request));
        viewer.assign("LANGUAGE_STRINGS", this.getJSLanguageStrings(request));
        viewer.assign("LANGUAGE", getLocale(request).toString());
        if (display) {
            this.preProcessDisplay(request, response);
        }
    }

    protected String preProcessTplName(HttpServletRequest request) {
        return "Header.tpl";
    }

    //Note : To get the right hook for immediate parent in PHP,
    // specially in case of deep hierarchy
    //TODO: Need to revisit this.
	/*function preProcessParentTplName(Vtiger_Request $request) {
		return parent::preProcessTplName($request);
	}*/

    protected void preProcessDisplay(HttpServletRequest request, HttpServletResponse response) throws Exception {
        RapidViewer viewer = this.getViewer(request);
        viewer.view(this.preProcessTplName(request), getModule(request), request, response);
    }


    @Override
    protected void postProcess(HttpServletRequest request, HttpServletResponse response) throws Exception {
        RapidViewer viewer = this.getViewer(request);
        UsersRecordModel currentUser = UsersRecordModel.getCurrentUserModel(request);
        viewer.assign("ACTIVITY_REMINDER", currentUser.getCurrentUserActivityReminderInSeconds());
        viewer.view("Footer.tpl", request, response);
    }

    private static final String JQUERY_VALIDATION_ENGINE_JS_PATH =
            "libraries/jquery/posabsolute-jQuery-Validation-Engine/js/languages/jquery.validationEngine-%s.js";

    /**
     * Retrieves headers scripts that need to loaded in the page
     *
     * @param request - request model
     * @return <array> - array of Vtiger_JsScript_Model
     */
    protected List<RapidJsScriptModel> getHeaderScripts(HttpServletRequest request) {
        List<RapidJsScriptModel> headerScriptInstances = new ArrayList<>();
        String languageHandlerShortName = getLanguageHandler(request).getShortLanguageName();
        String fileName = String.format(JQUERY_VALIDATION_ENGINE_JS_PATH, languageHandlerShortName);
        if (RapidResourceUtil.resourceNotExists(fileName)) {
            fileName = "~" + String.format(JQUERY_VALIDATION_ENGINE_JS_PATH, "en");
        }
        String[] jsFileNames = new String[]{"~" + fileName};
        Map<String, RapidJsScriptModel> jsScriptInstances = this.checkAndConvertJsScripts(jsFileNames);
        headerScriptInstances.addAll(jsScriptInstances.values());
        return headerScriptInstances;
    }

    protected Map<String, RapidJsScriptModel> checkAndConvertJsScripts(String[] jsFileNames) {
        String fileExtension = "js";

        Map<String, RapidJsScriptModel> jsScriptInstances = new LinkedHashMap<>();
        for (String jsFileName : jsFileNames) {
            // TODO Handle absolute inclusions (~/...) like in checkAndConvertCssStyles
            RapidJsScriptModel jsScript = new RapidJsScriptModel();

            // external javascript source file handling
            if (jsFileName.startsWith("http://") || jsFileName.startsWith("https://")) {
                jsScriptInstances.put(jsFileName, jsScript.setSrc(jsFileName));
                continue;
            }

            String completeFilePath = RapidLoader.resolveNameToPath(jsFileName, fileExtension);

            String filePath;
            if (RapidResourceUtil.resourceExists(completeFilePath)) {
                if (jsFileName.startsWith("~")) {
                    filePath = RapidStrUtil.ltrim(RapidStrUtil.ltrim(jsFileName, "~"), "/");
                } else {
                    filePath = jsFileName.replaceAll("\\.", "/") + "." + fileExtension;
                }

                jsScriptInstances.put(jsFileName, jsScript.setSrc(filePath));
            } else {
                String fallBackFilePath = RapidLoader.resolveNameToPath(RapidJavaScript.getBaseJavaScriptPath() + "/" + jsFileName, "js");
                if (RapidResourceUtil.resourceExists(fallBackFilePath)) {
                    jsScriptInstances.put(jsFileName, jsScript.setSrc(fallBackFilePath));
                }
            }
        }
        return jsScriptInstances;
    }

    protected List<RapidCssScriptModel> checkAndConvertCssStyles(String[] cssFileNames, HttpServletRequest request) {
        return checkAndConvertCssStyles(cssFileNames, "css", request);
    }

    /**
     * Function returns the css files
     *
     * @param cssFileNames  <Array>
     * @param fileExtension <String>
     * @return <Array of Vtiger_CssScript_Model>
     * <p>
     * First check if $cssFileName exists
     * if not, check under layout folder $cssFileName eg:layouts/vlayout/$cssFileName
     */
    protected List<RapidCssScriptModel> checkAndConvertCssStyles(String[] cssFileNames, String fileExtension,
                                                                 HttpServletRequest request) {

        List<RapidCssScriptModel> cssStyleInstances = new ArrayList<>();
        for (String cssFileName : cssFileNames) {
            RapidCssScriptModel cssScriptModel = new RapidCssScriptModel();

            if (cssFileName.startsWith("http://") || cssFileName.startsWith("https://")) {
                cssStyleInstances.add(cssScriptModel.setHref(cssFileName));
                continue;
            }
            String completeFilePath = RapidLoader.resolveNameToPath(cssFileName, fileExtension);
            String filePath;
            if (RapidResourceUtil.resourceExists(completeFilePath)) {
                if (cssFileName.startsWith("~")) {
                    filePath = RapidStrUtil.ltrim(RapidStrUtil.ltrim(cssFileName, "~"), "/");
                } else {
                    filePath = cssFileName.replaceAll("\\.", "/") + "." + fileExtension;
                    filePath = getThemeHandler(request).getStylePath(filePath);
                }
                cssStyleInstances.add(cssScriptModel.setHref(filePath));
            }
        }
        return cssStyleInstances;
    }

    /**
     * Retrieves css styles that need to loaded in the page
     *
     * @param request - request model
     * @return <array> - array of Vtiger_CssScript_Model
     */
    List<RapidCssScriptModel> getHeaderCss(HttpServletRequest request) {
        return new ArrayList<>();
    }

    /**
     * Function returns the Client side language string
     *
     * @param request HttpServletRequest
     */
    protected String getJSLanguageStrings(HttpServletRequest request) {
        String moduleName = getModule(request, false);
        return getLanguageHandler(request).export(moduleName, "jsLanguageStrings");
    }
}
